Skip to content

[sanitizer_common] Implement address sanitizer on AIX: platform specific support #131866

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 19 commits into
base: main
Choose a base branch
from

Conversation

jakeegan
Copy link
Member

@jakeegan jakeegan commented Mar 18, 2025

Add recognition of AIX and some platform specific changes. This lays the groundwork to implement AIX in sanitizer_common/asan.

Issue: #138916

Copy link

github-actions bot commented Mar 18, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

@jakeegan jakeegan changed the title [sanitizer_common] Add AIX specific platform support to sanitizer_common [sanitizer_common] Add AIX specific platform support Mar 19, 2025
@jakeegan
Copy link
Member Author

⚠️ C/C++ code formatter, clang-format found issues in your code. ⚠️

You can test this locally with the following command:
View the diff from clang-format here.

Should I be applying all the requested format changes? It's asking me to change some existing code that doesn't follow the format.

@llvmbot
Copy link
Member

llvmbot commented Mar 24, 2025

@llvm/pr-subscribers-compiler-rt-sanitizer

Author: Jake Egan (jakeegan)

Changes

Changes sanitizer_common to recognize AIX and makes some platform specific changes. This lays the groundwork to implement AIX in sanitizer_common/asan. More PRs to follow.


Full diff: https://github.com/llvm/llvm-project/pull/131866.diff

10 Files Affected:

  • (modified) compiler-rt/lib/sanitizer_common/sanitizer_allocator_internal.h (+5)
  • (modified) compiler-rt/lib/sanitizer_common/sanitizer_allocator_primary32.h (+1)
  • (modified) compiler-rt/lib/sanitizer_common/sanitizer_atomic_clang.h (+16)
  • (modified) compiler-rt/lib/sanitizer_common/sanitizer_common_libcdep.cpp (+6-1)
  • (modified) compiler-rt/lib/sanitizer_common/sanitizer_errno.h (+2)
  • (modified) compiler-rt/lib/sanitizer_common/sanitizer_flags.inc (+3)
  • (modified) compiler-rt/lib/sanitizer_common/sanitizer_platform.h (+11-3)
  • (modified) compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cpp (+54-14)
  • (modified) compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h (+75-19)
  • (modified) compiler-rt/lib/sanitizer_common/sanitizer_posix.cpp (+1-1)
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_allocator_internal.h b/compiler-rt/lib/sanitizer_common/sanitizer_allocator_internal.h
index 62523c7ae187c..e5b912d70e61e 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_allocator_internal.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_allocator_internal.h
@@ -23,7 +23,12 @@ namespace __sanitizer {
 typedef CompactSizeClassMap InternalSizeClassMap;
 
 struct AP32 {
+// For AIX 64-bit, the mmap begin is at address 0x0a00000000000000ULL.
+#if SANITIZER_AIX && SANITIZER_WORDSIZE == 64
+  static const uptr kSpaceBeg = 0x0a00000000000000ULL;
+#else
   static const uptr kSpaceBeg = 0;
+#endif
   static const u64 kSpaceSize = SANITIZER_MMAP_RANGE_SIZE;
   static const uptr kMetadataSize = 0;
   typedef InternalSizeClassMap SizeClassMap;
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_allocator_primary32.h b/compiler-rt/lib/sanitizer_common/sanitizer_allocator_primary32.h
index 602b197c42ae3..0faf9b3c151a4 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_allocator_primary32.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_allocator_primary32.h
@@ -288,6 +288,7 @@ class SizeClassAllocator32 {
   uptr ComputeRegionId(uptr mem) const {
     if (SANITIZER_SIGN_EXTENDED_ADDRESSES)
       mem &= (kSpaceSize - 1);
+    mem -= kSpaceBeg;
     const uptr res = mem >> kRegionSizeLog;
     CHECK_LT(res, kNumPossibleRegions);
     return res;
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_atomic_clang.h b/compiler-rt/lib/sanitizer_common/sanitizer_atomic_clang.h
index 1414092e38d7e..db4805468c2d5 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_atomic_clang.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_atomic_clang.h
@@ -14,6 +14,18 @@
 #ifndef SANITIZER_ATOMIC_CLANG_H
 #define SANITIZER_ATOMIC_CLANG_H
 
+// Helper to suppress warnings related to 8-byte atomic accesses when the target
+// is 32-bit AIX (where such accesses use libatomic).
+#if defined(_AIX) && !defined(__powerpc64__) && defined(__clang__)
+#define SANITIZER_IGNORE_ATOMIC_ALIGNMENT_BEGIN                                \
+  _Pragma("clang diagnostic push")                                             \
+      _Pragma("clang diagnostic ignored \"-Watomic-alignment\"")
+#define SANITIZER_IGNORE_ATOMIC_ALIGNMENT_END _Pragma("clang diagnostic pop")
+#else
+#define SANITIZER_IGNORE_ATOMIC_ALIGNMENT_BEGIN
+#define SANITIZER_IGNORE_ATOMIC_ALIGNMENT_END
+#endif
+
 namespace __sanitizer {
 
 // We use the compiler builtin atomic operations for loads and stores, which
@@ -35,6 +47,8 @@ inline void proc_yield(int cnt) {
 #endif
 }
 
+SANITIZER_IGNORE_ATOMIC_ALIGNMENT_BEGIN
+
 template <typename T>
 inline typename T::Type atomic_load(const volatile T *a, memory_order mo) {
   DCHECK(mo == memory_order_relaxed || mo == memory_order_consume ||
@@ -92,6 +106,8 @@ inline bool atomic_compare_exchange_weak(volatile T *a, typename T::Type *cmp,
   return atomic_compare_exchange_strong(a, cmp, xchg, mo);
 }
 
+SANITIZER_IGNORE_ATOMIC_ALIGNMENT_END
+
 }  // namespace __sanitizer
 
 #undef ATOMIC_ORDER
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_libcdep.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_common_libcdep.cpp
index f275e81ff0416..a770c8cf656b3 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_common_libcdep.cpp
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_libcdep.cpp
@@ -169,7 +169,12 @@ void ReserveShadowMemoryRange(uptr beg, uptr end, const char *name,
                      : !MmapFixedNoReserve(beg, size, name)) {
     Report(
         "ReserveShadowMemoryRange failed while trying to map 0x%zx bytes. "
-        "Perhaps you're using ulimit -v or ulimit -d\n",
+        "Perhaps you're using ulimit -v "
+#if SANITIZER_AIX && SANITIZER_WORDSIZE == 32
+        "or using large address-space model for 32-bit XCOFF by using ldedit "
+        "or setting LDR_CNTRL=MAXDATA or compiling the binary with -bmaxdata "
+#endif
+        "\n",
         size);
     Die();
   }
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_errno.h b/compiler-rt/lib/sanitizer_common/sanitizer_errno.h
index 46c85364cef56..cb31f02fcd88f 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_errno.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_errno.h
@@ -29,6 +29,8 @@
 #  define __errno_location ___errno
 #elif SANITIZER_WINDOWS
 #  define __errno_location _errno
+#elif SANITIZER_AIX
+#  define __errno_location _Errno
 #endif
 
 extern "C" int *__errno_location();
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_flags.inc b/compiler-rt/lib/sanitizer_common/sanitizer_flags.inc
index c1e3530618c20..a6c760b2387fb 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_flags.inc
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_flags.inc
@@ -269,6 +269,9 @@ COMMON_FLAG(bool, detect_write_exec, false,
 COMMON_FLAG(bool, test_only_emulate_no_memorymap, false,
             "TEST ONLY fail to read memory mappings to emulate sanitized "
             "\"init\"")
+COMMON_FLAG(bool, enable_unmalloced_free_check, !SANITIZER_AIX,
+            "if true, FreeNotMalloced error will be reported. Only disable "
+            "this error detecting on AIX by default for now.")
 // With static linking, dladdr((void*)pthread_join) or similar will return the
 // path to the main program. This flag will replace dlopen(<main program,...>
 // with dlopen(NULL,...), which is the correct way to get a handle to the main
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform.h
index 57966403c92a9..214d2865892df 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_platform.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform.h
@@ -14,7 +14,7 @@
 
 #if !defined(__linux__) && !defined(__FreeBSD__) && !defined(__NetBSD__) && \
     !defined(__APPLE__) && !defined(_WIN32) && !defined(__Fuchsia__) &&     \
-    !(defined(__sun__) && defined(__svr4__))
+    !(defined(__sun__) && defined(__svr4__)) && !defined(_AIX)
 #  error "This operating system is not supported"
 #endif
 
@@ -31,6 +31,12 @@
 #  define SANITIZER_LINUX 0
 #endif
 
+#if defined(_AIX)
+#  define SANITIZER_AIX 1
+#else
+#  define SANITIZER_AIX 0
+#endif
+
 #if defined(__GLIBC__)
 #  define SANITIZER_GLIBC 1
 #else
@@ -138,7 +144,7 @@
 
 #define SANITIZER_POSIX                                     \
   (SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_APPLE || \
-   SANITIZER_NETBSD || SANITIZER_SOLARIS)
+   SANITIZER_NETBSD || SANITIZER_SOLARIS || SANITIZER_AIX)
 
 #if __LP64__ || defined(_WIN64)
 #  define SANITIZER_WORDSIZE 64
@@ -392,7 +398,9 @@
 // (ie. same as double) to 128-bit long double.  On those, glibc symbols
 // involving long doubles come in two versions, and we need to pass the
 // correct one to dlvsym when intercepting them.
-#if SANITIZER_LINUX && (SANITIZER_S390 || SANITIZER_PPC32 || SANITIZER_PPC64V1)
+#if SANITIZER_LINUX &&                                        \
+    (SANITIZER_S390 || (SANITIZER_PPC32 && !SANITIZER_AIX) || \
+     SANITIZER_PPC64V1)
 #  define SANITIZER_NLDBL_VERSION "GLIBC_2.4"
 #endif
 
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cpp
index a5311d266b0c4..09a2fce1d856e 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cpp
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cpp
@@ -24,7 +24,7 @@
 // Must go after undef _FILE_OFFSET_BITS.
 #include "sanitizer_platform.h"
 
-#if SANITIZER_LINUX || SANITIZER_APPLE
+#if SANITIZER_LINUX || SANITIZER_APPLE || SANITIZER_AIX
 // Must go after undef _FILE_OFFSET_BITS.
 #include "sanitizer_glibc_version.h"
 
@@ -61,7 +61,9 @@
 #endif
 
 #if !SANITIZER_ANDROID
+#if !SANITIZER_AIX
 #include <sys/mount.h>
+#endif
 #include <sys/timeb.h>
 #include <utmpx.h>
 #endif
@@ -110,7 +112,11 @@ typedef struct user_fpregs elf_fpregset_t;
 #endif
 
 #if !SANITIZER_ANDROID
+#if !SANITIZER_AIX
 #include <ifaddrs.h>
+#else
+#include <netinet/in.h>
+#endif
 #include <sys/ucontext.h>
 #include <wordexp.h>
 #endif
@@ -173,6 +179,17 @@ typedef struct user_fpregs elf_fpregset_t;
 #include <sys/sockio.h>
 #endif
 
+#if SANITIZER_AIX
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <stropts.h>
+#include <sys/statfs.h>
+#include <netinet/ip_mroute.h>
+#if HAVE_RPC_XDR_H
+#include <tirpc/rpc/xdr.h>
+#endif
+#endif
+
 // Include these after system headers to avoid name clashes and ambiguities.
 #  include "sanitizer_common.h"
 #  include "sanitizer_internal_defs.h"
@@ -551,12 +568,39 @@ unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr);
 
   const unsigned IOCTL_NOT_PRESENT = 0;
 
+  // On AIX, some variables are unsigned long types.
+#if SANITIZER_AIX
+  uptr IOCTL_FIOASYNC = FIOASYNC;
+  uptr IOCTL_FIONBIO = FIONBIO;
+  uptr IOCTL_FIOSETOWN = FIOSETOWN;
+  uptr IOCTL_SIOCSPGRP = SIOCSPGRP;
+  uptr IOCTL_TIOCCONS = TIOCCONS;
+  uptr IOCTL_TIOCMBIC = TIOCMBIC;
+  uptr IOCTL_TIOCMBIS = TIOCMBIS;
+  uptr IOCTL_TIOCMSET = TIOCMSET;
+  uptr IOCTL_TIOCPKT = TIOCPKT;
+  uptr IOCTL_TIOCSETD = TIOCSETD;
+  uptr IOCTL_TIOCSPGRP = TIOCSPGRP;
+  uptr IOCTL_TIOCSTI = TIOCSTI;
+  uptr IOCTL_TIOCSWINSZ = TIOCSWINSZ;
+#else
   unsigned IOCTL_FIOASYNC = FIOASYNC;
+  unsigned IOCTL_FIONBIO = FIONBIO;
+  unsigned IOCTL_FIOSETOWN = FIOSETOWN;
+  unsigned IOCTL_SIOCSPGRP = SIOCSPGRP;
+  unsigned IOCTL_TIOCCONS = TIOCCONS;
+  unsigned IOCTL_TIOCMBIC = TIOCMBIC;
+  unsigned IOCTL_TIOCMBIS = TIOCMBIS;
+  unsigned IOCTL_TIOCMSET = TIOCMSET;
+  unsigned IOCTL_TIOCPKT = TIOCPKT;
+  unsigned IOCTL_TIOCSETD = TIOCSETD;
+  unsigned IOCTL_TIOCSPGRP = TIOCSPGRP;
+  unsigned IOCTL_TIOCSTI = TIOCSTI;
+  unsigned IOCTL_TIOCSWINSZ = TIOCSWINSZ;
+#endif
   unsigned IOCTL_FIOCLEX = FIOCLEX;
   unsigned IOCTL_FIOGETOWN = FIOGETOWN;
-  unsigned IOCTL_FIONBIO = FIONBIO;
   unsigned IOCTL_FIONCLEX = FIONCLEX;
-  unsigned IOCTL_FIOSETOWN = FIOSETOWN;
   unsigned IOCTL_SIOCADDMULTI = SIOCADDMULTI;
   unsigned IOCTL_SIOCATMARK = SIOCATMARK;
   unsigned IOCTL_SIOCDELMULTI = SIOCDELMULTI;
@@ -576,25 +620,17 @@ unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr);
   unsigned IOCTL_SIOCSIFMETRIC = SIOCSIFMETRIC;
   unsigned IOCTL_SIOCSIFMTU = SIOCSIFMTU;
   unsigned IOCTL_SIOCSIFNETMASK = SIOCSIFNETMASK;
-  unsigned IOCTL_SIOCSPGRP = SIOCSPGRP;
-  unsigned IOCTL_TIOCCONS = TIOCCONS;
   unsigned IOCTL_TIOCEXCL = TIOCEXCL;
   unsigned IOCTL_TIOCGETD = TIOCGETD;
   unsigned IOCTL_TIOCGPGRP = TIOCGPGRP;
   unsigned IOCTL_TIOCGWINSZ = TIOCGWINSZ;
-  unsigned IOCTL_TIOCMBIC = TIOCMBIC;
-  unsigned IOCTL_TIOCMBIS = TIOCMBIS;
   unsigned IOCTL_TIOCMGET = TIOCMGET;
-  unsigned IOCTL_TIOCMSET = TIOCMSET;
   unsigned IOCTL_TIOCNOTTY = TIOCNOTTY;
   unsigned IOCTL_TIOCNXCL = TIOCNXCL;
   unsigned IOCTL_TIOCOUTQ = TIOCOUTQ;
-  unsigned IOCTL_TIOCPKT = TIOCPKT;
+#if !SANITIZER_AIX
   unsigned IOCTL_TIOCSCTTY = TIOCSCTTY;
-  unsigned IOCTL_TIOCSETD = TIOCSETD;
-  unsigned IOCTL_TIOCSPGRP = TIOCSPGRP;
-  unsigned IOCTL_TIOCSTI = TIOCSTI;
-  unsigned IOCTL_TIOCSWINSZ = TIOCSWINSZ;
+#endif
 #if SANITIZER_LINUX && !SANITIZER_ANDROID
   unsigned IOCTL_SIOCGETSGCNT = SIOCGETSGCNT;
   unsigned IOCTL_SIOCGETVIFCNT = SIOCGETVIFCNT;
@@ -1103,6 +1139,8 @@ COMPILER_CHECK(sizeof(__sanitizer_dirent) <= sizeof(dirent));
 CHECK_SIZE_AND_OFFSET(dirent, d_ino);
 #if SANITIZER_APPLE
 CHECK_SIZE_AND_OFFSET(dirent, d_seekoff);
+#elif SANITIZER_AIX
+CHECK_SIZE_AND_OFFSET(dirent, d_offset);
 #elif SANITIZER_FREEBSD
 // There is no 'd_off' field on FreeBSD.
 #else
@@ -1191,8 +1229,10 @@ CHECK_SIZE_AND_OFFSET(tm, tm_year);
 CHECK_SIZE_AND_OFFSET(tm, tm_wday);
 CHECK_SIZE_AND_OFFSET(tm, tm_yday);
 CHECK_SIZE_AND_OFFSET(tm, tm_isdst);
+#if !SANITIZER_AIX
 CHECK_SIZE_AND_OFFSET(tm, tm_gmtoff);
 CHECK_SIZE_AND_OFFSET(tm, tm_zone);
+#endif
 
 #if SANITIZER_LINUX
 CHECK_TYPE_SIZE(mntent);
@@ -1242,7 +1282,7 @@ CHECK_TYPE_SIZE(clock_t);
 CHECK_TYPE_SIZE(clockid_t);
 #endif
 
-#if !SANITIZER_ANDROID
+#if !SANITIZER_ANDROID && !SANITIZER_AIX
 CHECK_TYPE_SIZE(ifaddrs);
 CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_next);
 CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_name);
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h
index 1a7d9e64048eb..4f5022a75d3cc 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h
@@ -14,7 +14,7 @@
 #ifndef SANITIZER_PLATFORM_LIMITS_POSIX_H
 #define SANITIZER_PLATFORM_LIMITS_POSIX_H
 
-#if SANITIZER_LINUX || SANITIZER_APPLE
+#if SANITIZER_LINUX || SANITIZER_APPLE || SANITIZER_AIX
 
 #include "sanitizer_internal_defs.h"
 #include "sanitizer_platform.h"
@@ -29,7 +29,7 @@
 #define SANITIZER_HAS_STAT64 0
 #define SANITIZER_HAS_STATFS64 0
 #endif
-#elif SANITIZER_GLIBC || SANITIZER_ANDROID
+#elif SANITIZER_GLIBC || SANITIZER_ANDROID || SANITIZER_AIX
 #define SANITIZER_HAS_STAT64 1
 #define SANITIZER_HAS_STATFS64 1
 #endif
@@ -319,7 +319,7 @@ struct __sanitizer_iovec {
   usize iov_len;
 };
 
-#if !SANITIZER_ANDROID
+#if !SANITIZER_ANDROID && !SANITIZER_AIX
 struct __sanitizer_ifaddrs {
   struct __sanitizer_ifaddrs *ifa_next;
   char *ifa_name;
@@ -341,7 +341,7 @@ typedef unsigned long __sanitizer_pthread_key_t;
 typedef unsigned __sanitizer_pthread_key_t;
 #endif
 
-#if SANITIZER_LINUX && !SANITIZER_ANDROID
+#if (SANITIZER_LINUX && !SANITIZER_ANDROID) || SANITIZER_AIX
 
 struct __sanitizer_XDR {
   int x_op;
@@ -433,8 +433,10 @@ struct __sanitizer_tm {
   int tm_wday;
   int tm_yday;
   int tm_isdst;
+#if !SANITIZER_AIX
   long int tm_gmtoff;
   const char *tm_zone;
+#endif
 };
 
 #if SANITIZER_LINUX
@@ -478,11 +480,19 @@ struct __sanitizer_msghdr {
   struct __sanitizer_iovec *msg_iov;
   uptr msg_iovlen;
   void *msg_control;
+#if !SANITIZER_AIX
   uptr msg_controllen;
+#else
+  unsigned msg_controllen;
+#endif
   int msg_flags;
 };
 struct __sanitizer_cmsghdr {
+#if !SANITIZER_AIX
   uptr cmsg_len;
+#else
+  unsigned cmsg_len;
+#endif
   int cmsg_level;
   int cmsg_type;
 };
@@ -512,8 +522,13 @@ struct __sanitizer_dirent {
 };
 #  else
 struct __sanitizer_dirent {
+#if SANITIZER_AIX
+  uptr d_offset;
+  uptr d_ino;
+#else
   uptr d_ino;
   uptr d_off;
+#endif
   unsigned short d_reclen;
   // more fields that we don't care about
 };
@@ -529,7 +544,10 @@ struct __sanitizer_dirent64 {
 extern unsigned struct_sock_fprog_sz;
 #endif
 
-#if defined(__x86_64__) && !defined(_LP64)
+#if SANITIZER_AIX
+typedef int __sanitizer_clock_t;
+typedef int __sanitizer_clockid_t;
+#elif defined(__x86_64__) && !defined(_LP64)
 typedef long long __sanitizer_clock_t;
 #else
 typedef long __sanitizer_clock_t;
@@ -589,6 +607,14 @@ struct __sanitizer_sigset_t {
   // The size is determined by looking at sizeof of real sigset_t on linux.
   uptr val[128 / sizeof(uptr)];
 };
+#elif SANITIZER_AIX
+struct __sanitizer_sigset_t {
+#if SANITIZER_WORDSIZE == 64
+  uptr val[4];
+#else
+  uptr val[2];
+#endif
+};
 #endif
 
 struct __sanitizer_siginfo_pad {
@@ -779,8 +805,12 @@ struct __sanitizer_addrinfo {
   int ai_family;
   int ai_socktype;
   int ai_protocol;
-#if SANITIZER_ANDROID || SANITIZER_APPLE
+#if SANITIZER_ANDROID || SANITIZER_APPLE || SANITIZER_AIX
+#if SANITIZER_AIX // AIX ai_addrlen type is size_t
+  uptr ai_addrlen;
+#else
   unsigned ai_addrlen;
+#endif
   char *ai_canonname;
   void *ai_addr;
 #else // LINUX
@@ -789,6 +819,9 @@ struct __sanitizer_addrinfo {
   char *ai_canonname;
 #endif
   struct __sanitizer_addrinfo *ai_next;
+#if SANITIZER_AIX
+  int ai_eflags;
+#endif
 };
 
 struct __sanitizer_hostent {
@@ -805,7 +838,7 @@ struct __sanitizer_pollfd {
   short revents;
 };
 
-#if SANITIZER_ANDROID || SANITIZER_APPLE
+#if SANITIZER_ANDROID || SANITIZER_APPLE || SANITIZER_AIX
 typedef unsigned __sanitizer_nfds_t;
 #else
 typedef unsigned long __sanitizer_nfds_t;
@@ -843,6 +876,10 @@ struct __sanitizer_wordexp_t {
   uptr we_wordc;
   char **we_wordv;
   uptr we_offs;
+#if SANITIZER_AIX
+  int we_sflags;
+  uptr we_soffs;
+#endif
 };
 
 #if SANITIZER_LINUX && !SANITIZER_ANDROID
@@ -1102,12 +1139,39 @@ extern unsigned fpos_t_sz;
 // when it can not be determined without including any system headers.
 extern const unsigned IOCTL_NOT_PRESENT;
 
+#if SANITIZER_AIX
+extern uptr IOCTL_FIOASYNC;
+extern uptr IOCTL_FIONBIO;
+extern uptr IOCTL_FIOSETOWN;
+extern uptr IOCTL_SIOCSPGRP;
+extern uptr IOCTL_TIOCCONS;
+extern uptr IOCTL_TIOCMBIC;
+extern uptr IOCTL_TIOCMBIS;
+extern uptr IOCTL_TIOCMSET;
+extern uptr IOCTL_TIOCPKT;
+extern uptr IOCTL_TIOCSETD;
+extern uptr IOCTL_TIOCSPGRP;
+extern uptr IOCTL_TIOCSTI;
+extern uptr IOCTL_TIOCSWINSZ;
+#else
 extern unsigned IOCTL_FIOASYNC;
+extern unsigned IOCTL_FIONBIO;
+extern unsigned IOCTL_FIOSETOWN;
+extern unsigned IOCTL_SIOCSPGRP;
+extern unsigned IOCTL_TIOCCONS;
+extern unsigned IOCTL_TIOCMBIC;
+extern unsigned IOCTL_TIOCMBIS;
+extern unsigned IOCTL_TIOCMSET;
+extern unsigned IOCTL_TIOCPKT;
+extern unsigned IOCTL_TIOCSETD;
+extern unsigned IOCTL_TIOCSPGRP;
+extern unsigned IOCTL_TIOCSTI;
+extern unsigned IOCTL_TIOCSWINSZ;
+#endif
+
 extern unsigned IOCTL_FIOCLEX;
 extern unsigned IOCTL_FIOGETOWN;
-extern unsigned IOCTL_FIONBIO;
 extern unsigned IOCTL_FIONCLEX;
-extern unsigned IOCTL_FIOSETOWN;
 extern unsigned IOCTL_SIOCADDMULTI;
 extern unsigned IOCTL_SIOCATMARK;
 extern unsigned IOCTL_SIOCDELMULTI;
@@ -1127,25 +1191,17 @@ extern unsigned IOCTL_SIOCSIFFLAGS;
 extern unsigned IOCTL_SIOCSIFMETRIC;
 extern unsigned IOCTL_SIOCSIFMTU;
 extern unsigned IOCTL_SIOCSIFNETMASK;
-extern unsigned IOCTL_SIOCSPGRP;
-extern unsigned IOCTL_TIOCCONS;
 extern unsigned IOCTL_TIOCEXCL;
 extern unsigned IOCTL_TIOCGETD;
 extern unsigned IOCTL_TIOCGPGRP;
 extern unsigned IOCTL_TIOCGWINSZ;
-extern unsigned IOCTL_TIOCMBIC;
-extern unsigned IOCTL_TIOCMBIS;
 extern unsigned IOCTL_TIOCMGET;
-extern unsigned IOCTL_TIOCMSET;
 extern unsigned IOCTL_TIOCNOTTY;
 extern unsigned IOCTL_TIOCNXCL;
 extern unsigned IOCTL_TIOCOUTQ;
-extern unsigned IOCTL_TIOCPKT;
+#if !SANITIZER_AIX
 extern unsigned IOCTL_TIOCSCTTY;
-extern unsigned IOCTL_TIOCSETD;
-extern unsigned IOCTL_TIOCSPGRP;
-extern unsigned IOCTL_TIOCSTI;
-extern unsigned IOCTL_TIOCSWINSZ;
+#endif
 #if SANITIZER_LINUX && !SANITIZER_ANDROID
 extern unsigned IOCTL_SIOCGETSGCNT;
 extern unsigned IOCTL_SIOCGETVIFCNT;
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_posix.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_posix.cpp
index 69af6465a62c2..44c40036babb2 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_posix.cpp
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_posix.cpp
@@ -27,7 +27,7 @@
 #include <signal.h>
 #include <sys/mman.h>
 
-#if SANITIZER_FREEBSD
+#if SANITIZER_FREEBSD || SANITIZER_AIX
 // The MAP_NORESERVE define has been removed in FreeBSD 11.x, and even before
 // that, it was never implemented.  So just define it to zero.
 #undef  MAP_NORESERVE

@jakeegan jakeegan changed the title [sanitizer_common] Add AIX specific platform support [sanitizer_common] Implement address sanitizer on AIX: add platform specific support (3/n) Mar 24, 2025
@llvmbot llvmbot added the compiler-rt:asan Address sanitizer label Apr 24, 2025
@jakeegan jakeegan changed the title [sanitizer_common] Implement address sanitizer on AIX: add platform specific support (3/n) [sanitizer_common][asan] Implement address sanitizer on AIX: add platform specific support (3/n) Apr 24, 2025
Copy link

github-actions bot commented Apr 29, 2025

✅ With the latest revision this PR passed the Python code formatter.

@jakeegan jakeegan changed the title [sanitizer_common][asan] Implement address sanitizer on AIX: add platform specific support (3/n) [sanitizer_common][asan] Implement address sanitizer on AIX: add platform specific support (3/6) Apr 29, 2025
@jakeegan
Copy link
Member Author

Refreshed this PR and all subsequent PRs, so they're all ready to review again.

@jakeegan jakeegan changed the title [sanitizer_common][asan] Implement address sanitizer on AIX: add platform specific support (3/6) [sanitizer_common][asan] Implement address sanitizer on AIX: adjust platform specific support (3/6) May 6, 2025
@jakeegan jakeegan changed the title [sanitizer_common][asan] Implement address sanitizer on AIX: adjust platform specific support (3/6) [sanitizer_common][asan] Implement address sanitizer on AIX: adjust platform specific support (3/n) May 7, 2025
@jakeegan jakeegan changed the title [sanitizer_common][asan] Implement address sanitizer on AIX: adjust platform specific support (3/n) [sanitizer_common][asan] Implement address sanitizer on AIX: platform specific support (3/n) May 7, 2025
@vitalybuka
Copy link
Collaborator

⚠️ C/C++ code formatter, clang-format found issues in your code. ⚠️
You can test this locally with the following command:
View the diff from clang-format here.

Should I be applying all the requested format changes? It's asking me to change some existing code that doesn't follow the format.

If large reformat, like here, is required, ideally, if it's not hard, create a NFC PR which reformat corresponding block. And after landing that PR, create PR with real changes.

For smaller PRs I don't mind mixing autoformat changes.

BTW. this one can be split into more parts.

@jakeegan jakeegan changed the title [sanitizer_common][asan] Implement address sanitizer on AIX: platform specific support (3/n) [sanitizer_common][asan] Implement address sanitizer on AIX: platform specific support May 12, 2025
@jakeegan jakeegan changed the title [sanitizer_common][asan] Implement address sanitizer on AIX: platform specific support [sanitizer_common] Implement address sanitizer on AIX: platform specific support May 13, 2025
@@ -14,27 +14,27 @@
#ifndef SANITIZER_PLATFORM_LIMITS_POSIX_H
#define SANITIZER_PLATFORM_LIMITS_POSIX_H
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe sanitizer_platform_limits_aix.h ?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same question as above. Needing dual maintenance of parallel copies is not good.

@@ -24,7 +24,7 @@
// Must go after undef _FILE_OFFSET_BITS.
#include "sanitizer_platform.h"

#if SANITIZER_LINUX || SANITIZER_APPLE || SANITIZER_HAIKU
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe sanitizer_platform_limits_aix.cpp ?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why though? AIX is a POSIX platform and the logic (and structure) here seems to be common except for the usual type/structure size/layout differences.

Copy link
Collaborator

@hubert-reinterpretcast hubert-reinterpretcast left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Partial review comments

@@ -405,7 +411,9 @@
// (ie. same as double) to 128-bit long double. On those, glibc symbols
// involving long doubles come in two versions, and we need to pass the
// correct one to dlvsym when intercepting them.
#if SANITIZER_LINUX && (SANITIZER_S390 || SANITIZER_PPC32 || SANITIZER_PPC64V1)
#if SANITIZER_LINUX && \
(SANITIZER_S390 || (SANITIZER_PPC32 && !SANITIZER_AIX) || \
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this change necessary? SANITIZER_LINUX is not set at the same time as SANITIZER_AIX, right?

@@ -557,14 +572,45 @@ unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr);

const unsigned IOCTL_NOT_PRESENT = 0;

// On AIX, some variables are unsigned long types.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The vertical separation and intermixing between the changes here is not in a good shape for review.

Suggestion:

Add

#if SANITIZER_AIX
using ioctl_alttype = uptr;
#else
using ioctl_alttype = unsigned;
#endif

and change the specific lines affected by replacing unsigned with ioctl_alttype.

Comment on lines 442 to 444
#else
long int tm_gmtoff;
#endif
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Formatting inconsistency?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jakeegan, I think this (and similar other cases) points to a need to land an NFC auto-format patch on more parts of the code first.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Opened #147864

@@ -14,7 +14,11 @@ include(CompilerRTDarwinUtils)
check_include_file(unwind.h HAVE_UNWIND_H)

# Used by sanitizer_common and tests.
check_include_file(rpc/xdr.h HAVE_RPC_XDR_H)
if (${CMAKE_SYSTEM_NAME} MATCHES AIX)
check_include_file(tirpc/rpc/xdr.h HAVE_RPC_XDR_H)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not specific to this patch: I am a bit concerned about this. If the CI or build system does not have this header, then changes that break the correspondence in layout would not be identified.

A separate patch should be posted to require the presence of this header (with an opt-out via CMake option). @vitalybuka, what process would you advise in terms of giving advance warning for buildbot maintainers?

Copy link
Collaborator

@hubert-reinterpretcast hubert-reinterpretcast left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

More partial review comments


#if defined(__sparc__)
# if defined(__sparc__)
// FIXME: This can't be included from tsan which does not support sparc yet.
#include "sanitizer_glibc_version.h"
#endif
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inconsistent whitespace?

@@ -319,7 +319,7 @@ struct __sanitizer_iovec {
usize iov_len;
};

#if !SANITIZER_ANDROID
# if !SANITIZER_ANDROID && !SANITIZER_AIX
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whitespace and comment update missing on line 336:

typedef int __sanitizer_clock_t;
#elif defined(__x86_64__) && !defined(_LP64)
typedef int __sanitizer_clockid_t;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move __sanitizer_clockid_t definition to the next block where it is defined for other platforms.

@@ -609,7 +627,15 @@ struct __sanitizer_sigset_t {
// The size is determined by looking at sizeof of real sigset_t on linux.
uptr val[128 / sizeof(uptr)];
};
#endif
# elif SANITIZER_AIX
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whitespace is inconsistent with line 625:

Copy link
Collaborator

@hubert-reinterpretcast hubert-reinterpretcast left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My last comments for this revision of the PR.

@@ -809,6 +839,9 @@ struct __sanitizer_addrinfo {
char *ai_canonname;
#endif
struct __sanitizer_addrinfo *ai_next;
# if SANITIZER_AIX
int ai_eflags;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason for this to not be subject to a CHECK_SIZE_AND_OFFSET call?

Comment on lines +900 to +901
int we_sflags;
uptr we_soffs;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same question re: CHECK_SIZE_AND_OFFSET.

@@ -1121,12 +1158,41 @@ extern unsigned fpos_t_sz;
// when it can not be determined without including any system headers.
extern const unsigned IOCTL_NOT_PRESENT;

# if SANITIZER_AIX
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment on lines +30 to 32
# if SANITIZER_FREEBSD || SANITIZER_AIX
// The MAP_NORESERVE define has been removed in FreeBSD 11.x, and even before
// that, it was never implemented. So just define it to zero.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment needs update. Whitespace should also be updated for the #endif.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants